package co.edu.unal.satacredito.rest.auth;

import com.sun.jersey.api.NotFoundException;
import com.sun.jersey.api.client.Client;
import com.sun.jersey.api.client.ClientResponse;
import com.sun.jersey.api.client.WebResource;
import com.sun.jersey.api.representation.Form;
import com.sun.jersey.api.view.Viewable;
import com.sun.jersey.oauth.server.api.providers.DefaultOAuthProvider;
import com.sun.jersey.oauth.server.api.providers.DefaultOAuthProvider.Consumer;

import javax.servlet.http.HttpServletRequest;
import javax.ws.rs.FormParam;
import javax.ws.rs.GET;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.PathParam;
import javax.ws.rs.Produces;
import javax.ws.rs.QueryParam;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.SecurityContext;
import javax.ws.rs.core.UriBuilder;
import java.net.URI;
import java.util.Collection;

/**
 * Root resource we are using for redirecting to the user-specific URL
 */
@Path("/")
public class RootResource extends ResourceBase {
	
    /**
     * Reads the user principal and based on that redirects to the user-specific URL
     *
     * @param security security context
     * @return response object representing SEE_OTHER response with the user-specific URL
     */
    @GET
    public Response get(@Context SecurityContext security) {
        checkUser(); // forces login (if not done yet)
        return Response.seeOther(UriBuilder.fromPath("{user}/statuses/").build(security.getUserPrincipal().getName())).build();
    }

    /**
     * To keep it simple for the demo OAuth client and a need of handling redirects,
     * GET request on the root resource will return the statuses of the active user.
     *
     * @param security security context
     * @return list of all user statuses for authenticated user
     */
    @GET
    @Produces({MediaType.APPLICATION_XML, MediaType.APPLICATION_JSON})
    public Collection<Status> getXmlJson(@Context SecurityContext security) {
        checkUser();
        return getUser(security.getUserPrincipal().getName()).getStatuses().getXml();
    }

    /**
     * Sub-resource locator for {@link UserResource}.
     *
     * @param user user name
     * @return user resource corresponding to the user name
     */
    @Path("{user}/")
    public UserResource getUser(@PathParam("user") String user) {
        return new UserResource(user, this);
    }

    /**
     * Forces authentication (configured in web.xml) and redirects
     * to the URL passed in the {@code redirect} query parameter.
     *
     * @param redirect URL to redirect to
     * @return SEE_OTHER response
     */
    @Path("login")
    @GET
    public Response get(@QueryParam ("redirect") URI redirect) {
        return Response.seeOther(redirect).build();
    }

    /**
     * Performs the user logout and redirects to the root resource.
     *
     * @param request injected instance of {@link HttpServletRequest}
     * @return redirect to the root resource
     */
    @Path("logout")
    @POST
    public Response logout(@Context HttpServletRequest request) {
        request.getSession().invalidate();
        return Response.seeOther(UriBuilder.fromPath("/").build()).build();
    }

    /**
     * Returns new user registration page.
     *
     * @return representation of user registration page
     */
    @Path("register")
    @GET
    public Viewable registrationPage() {
        return new Viewable("/register");
    }

    /**
     * Registers a new user using GlassFish REST Admin interface.
     *
     * @param username username of newly registered user
     * @param password password of newly registered user
     * @return response with redirect to root resource or with error indication
     */
    @Path("register")
    @POST
    public Response register(@FormParam("username") String username, @FormParam("password") String password) {
        Client client = Client.create();
        WebResource r = client.resource("http://localhost:4848/management/domain/configs/config/server-config/security-service/auth-realm/file/create-user");
        Form f = new Form();
        f.add("id", username);
        f.add("AS_ADMIN_USERPASSWORD", password);
        f.add("groups", "users");
        f.add("target", "server");
        ClientResponse response = r.type(MediaType.APPLICATION_FORM_URLENCODED_TYPE).entity(f).post(ClientResponse.class);
        if (response.getStatus() != ClientResponse.Status.OK.getStatusCode()) {
            return Response.status(response.getStatus()).build();
        }
        return Response.seeOther(UriBuilder.fromPath("/").build()).build();
    }
}
